package com.spring.boot.email.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.spring.boot.email.dto.BaseResult;
import com.spring.boot.email.entity.*;
import com.spring.boot.email.service.EmailService;
import org.apache.tomcat.util.codec.binary.Base64;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.mail.javamail.JavaMailSenderImpl;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import javax.mail.*;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeUtility;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;


@Service
public class EmailServiceImpl implements EmailService {
    private static final Logger logger = LoggerFactory.getLogger(EmailServiceImpl.class);
    @Autowired
    private JavaMailSenderImpl javaMailSender;

    /**
     * 发送 HTML格式带附件和抄送的邮件
     *
     * @param emailMessageJson
     * @param mailSenderConfigJson
     * @param files
     * @return
     */
    @Override
    public BaseResult sendHtmlMail(String emailMessageJson, String mailSenderConfigJson, MultipartFile[] files) {
        BaseResult baseResult = BaseResult.success();
        MimeMessage message = javaMailSender.createMimeMessage();
        try {
            EmailMessage emailMessage = JSONObject.parseObject(emailMessageJson, EmailMessage.class);
            MailSenderConfig mailSenderConfig = JSONObject.parseObject(mailSenderConfigJson, MailSenderConfig.class);

            // 校验数据
            checkMailData(emailMessage, mailSenderConfig);
            MimeMessageHelper helper = new MimeMessageHelper(message, true);
            helper.setFrom(emailMessage.getSender());
            helper.setTo(emailMessage.getReceiver());
            helper.setSubject(emailMessage.getSubject());
            //true 表示启动HTML格式的邮件
            helper.setText(emailMessage.getContext(), true);
            // 抄送人
            if (emailMessage.getCc() != null) {
                helper.setCc(emailMessage.getCc().split(","));
            }
            // 密送人
            if (emailMessage.getBcc() != null) {
                helper.setBcc(emailMessage.getBcc().split(","));
            }
            // 附件
            if (files != null && files.length > 0) {
                for (MultipartFile multipartFile : files) {
                    helper.addAttachment(multipartFile.getOriginalFilename(), multipartFile);
                }
            }
            helper.setSentDate(new Date());
            // JavaMailSender动态封装邮件服务器数据
            this.javaMailSenderConf(mailSenderConfig);
            javaMailSender.send(message);

        } catch (Exception e) {
            e.printStackTrace();
            baseResult = BaseResult.fail(e.getMessage());
        }
        return baseResult;
    }

    @Override
    public BaseResult getEmail(ReceiveEmail ReceiveEmail) {
        BaseResult baseResult = BaseResult.success();
        EmailVo emailVo = new EmailVo();
        // 准备连接服务器的会话信息
        Properties props = new Properties();
        props.setProperty("mail.store.protocol", ReceiveEmail.getProtocol());
        if (StringUtils.pathEquals(ReceiveEmail.getProtocol(), "imap")) {
            props.setProperty("mail.imap.host", ReceiveEmail.getHost());
            props.setProperty("mail.imap.port", ReceiveEmail.getPort());
        } else {
            props.setProperty("mail.pop3.host", ReceiveEmail.getHost());
            props.setProperty("mail.pop3.port", ReceiveEmail.getPort());
        }

        // 创建Session实例对象
        Session session = Session.getInstance(props);
        // 创建IMAP协议的Store对象
        Store store = null;

        try {
            store = session.getStore(ReceiveEmail.getProtocol());
            // 连接邮件服务器
            store.connect(ReceiveEmail.getUsername(), ReceiveEmail.getPassword());
            // 获得收件箱
            Folder folder = store.getFolder("INBOX");
            // 以读写模式打开收件箱
            folder.open(Folder.READ_WRITE);
            // 获得收件箱的邮件列表
            Message[] messages = folder.getMessages();
            emailVo.setCount(folder.getMessageCount());
            emailVo.setUnReadCount(folder.getUnreadMessageCount());
            // 解析邮件
            List<EmailInfos> emailInfosList = new ArrayList<>();
            for (int i = 0; i < messages.length; i++) {
                EmailInfos email = new EmailInfos();
                MimeMessage msg = (MimeMessage) messages[i];
                msg.setFlag(Flags.Flag.SEEN, true);
                email.setReceiver(ReceiveEmail.getUsername());
                //获得邮件的发送者、主题和正文
                // 发件人信息
                Address[] froms = msg.getFrom();
                if (!StringUtils.isEmpty(froms)) {
                    InternetAddress addr = (InternetAddress) froms[0];
                    email.setSender(addr.getAddress());
                } else {
                    email.setSender("无");
                }
                email.setSubject(transferChinese(msg.getSubject()));
                email.setSentDate(msg.getSentDate());
                // 获取 邮件正文
                StringBuffer content = new StringBuffer();
                getMailTextContent(msg, content);
                email.setContext(String.valueOf(content));
                // 获取 邮件附件
                Map<String, String> inputStreamMap = new HashMap<>();
                getMailAttachment(msg, inputStreamMap);
                email.setAttachments(inputStreamMap);
                emailInfosList.add(email);
            }
            emailVo.setEmailInfosList(emailInfosList);
            baseResult.setData(emailVo);
            folder.close();
            store.close();
        } catch (Exception e) {
            e.printStackTrace();
            baseResult = BaseResult.fail(e.getMessage());
        }
        return  baseResult;
    }

    /**
     * 获取邮件正文
     * @param part
     * @param content
     * @throws MessagingException
     * @throws IOException
     */
    private void getMailTextContent(Part part, StringBuffer content) throws MessagingException, IOException {
        boolean isContainTextAttach = part.getContentType().indexOf("name") > 0;
        if (part.isMimeType("text/*") && !isContainTextAttach) {
            content.append(part.getContent().toString());
        } else if (part.isMimeType("message/rfc822")) {
            getMailTextContent((Part)part.getContent(),content);
        } else if (part.isMimeType("multipart/*")) {
            Multipart multipart = (Multipart) part.getContent();
            int partCount = multipart.getCount();
            for (int i = 0; i < partCount; i++) {
                BodyPart bodyPart = multipart.getBodyPart(i);
                getMailTextContent(bodyPart,content);
            }
        }
    }

    /**
     * 获取邮件附件
     * @param part
     * @param inputStreamMap
     * @throws Exception
     */
    private void getMailAttachment(Part part, Map<String, String> inputStreamMap) throws Exception {
        String fileName;
        if (part.isMimeType("multipart/*")) {
            Multipart mp = (Multipart) part.getContent();
            for (int i = 0; i < mp.getCount(); i++) {
                StringBuffer stringBuffer = new StringBuffer();
                BodyPart mPart = mp.getBodyPart(i);
                String disposition = mPart.getDisposition();
                // 附件
                if ((disposition != null)
                        && ((disposition.equals(Part.ATTACHMENT)) || (disposition
                        .equals(Part.INLINE)))) {
                    // 避免中文乱码
                    fileName = MimeUtility.decodeText(mPart.getFileName());
                    InputStream in = mPart.getInputStream();;
                    byte[] data = inToByte(in);
                    inputStreamMap.put(fileName, new String(Base64.encodeBase64(data)));
                } else if (mPart.isMimeType("multipart/*")) {
                    getMailAttachment(mPart, inputStreamMap);
                } else {
                    fileName = mPart.getFileName();
                    if ((fileName != null)) {
                        fileName = MimeUtility.decodeText(fileName);
                        InputStream in = mPart.getInputStream();;
                        byte[] data = inToByte(in);
                        inputStreamMap.put(fileName, new String(Base64.encodeBase64(data)));
                    }
                }
            }
        } else if (part.isMimeType("message/rfc822")) {
            getMailAttachment((Part) part.getContent(), inputStreamMap);
        }

    }

    /**
     * // 读取图片字节数组
     * @param in
     * @return
     */
    private byte[] inToByte(InputStream in) {
        byte[] data = null;
        try {
            ByteArrayOutputStream swapStream = new ByteArrayOutputStream();
            byte[] buff = new byte[100];
            int rc = 0;
            while ((rc = in.read(buff, 0, 100)) > 0) {
                swapStream.write(buff, 0, rc);
            }
            data = swapStream.toByteArray();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (in != null) {
                try {
                    in.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return data;
    }

    /**
     * 把邮件主题转换为中文
     *
     * @param strText
     * @return
     */
    private String transferChinese(String strText) {
        try {
            if (StringUtils.isEmpty(strText)) {
                return null;
            }
            strText = MimeUtility.encodeText(new String(strText.getBytes(),
                    "UTF-8"), "UTF-8", "B");
            strText = MimeUtility.decodeText(strText);
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        }
        return strText;
    }


    private void javaMailSenderConf(MailSenderConfig mailSenderConfig) {
        javaMailSender.setHost(mailSenderConfig.getHost());
        javaMailSender.setPort(Integer.parseInt(mailSenderConfig.getPort()));
        javaMailSender.setUsername(mailSenderConfig.getFrom());
        javaMailSender.setPassword(mailSenderConfig.getPassword());
        Properties p = new Properties();
        p.setProperty("mail.smtp.auth", "true");
        p.setProperty("mail.debug", "true");
        p.setProperty("mail.stmp.ssl.enable", "true");
        p.setProperty("mail.smtp.starttls.enable", "true");
        javaMailSender.setJavaMailProperties(p);
    }

    private void checkMailData(EmailMessage emailMessage, MailSenderConfig mailSenderConfig) {
        if (StringUtils.isEmpty(emailMessage.getReceiver())) {
            throw new RuntimeException("邮件收信人不能为空");
        }
        if (StringUtils.isEmpty(emailMessage.getSubject())) {
            throw new RuntimeException("邮件主题不能为空");
        }
        if (StringUtils.isEmpty(emailMessage.getContext())) {
            throw new RuntimeException("邮件内容不能为空");
        }
        if (StringUtils.isEmpty(mailSenderConfig.getHost())) {
            throw new RuntimeException("邮件服务器地址不能为空");
        }
        if (StringUtils.isEmpty(mailSenderConfig.getPort())) {
            throw new RuntimeException("邮件服务器端口不能为空");
        }
        if (StringUtils.isEmpty(mailSenderConfig.getFrom())) {
            throw new RuntimeException("邮件服务器账号不能为空");
        }
        if (StringUtils.isEmpty(mailSenderConfig.getPassword())) {
            throw new RuntimeException("邮件服务器密码不能为空");
        }
    }




}
